﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using OffInvoiceExcelAddIn.XmlMngFiles;
using System.IO;
using System.Xml.Serialization;

namespace OffInvoiceExcelAddIn
{
    public partial class FrmSettings : Form
    {
        #region "Properties"

        /// <summary>
        /// Propiedad de tipo ConfigData la cual contiene la información necesaria para rellenar los campos
        /// del formulario.
        /// Es la representación del archivo XML de configuración como un objeto .NET
        /// </summary>
        public ConfigData Configuration { get; set; }

        public TimeStampConfig TstConfig { get; set; }

        #endregion

        #region "Constructors"

        /// <summary>
        /// Constructor que inicializa todos los componentes gráficos del formulario.
        /// </summary>
        public FrmSettings()
        {
            InitializeComponent();
        }

        #endregion

        #region "EventHandler"

        /// <summary>
        /// Método que maneja el evento que se produce al hacer click con el ratón sobre el botón de aceptar.
        /// Comprueba que los datos sean correctos y guarda dichos datos en la propiedad de configuración para
        /// mas tarde almacenarlos en el archivo de configuración.
        /// Si el proceso ha ido bien se muestra un mensaje donde se dice que la nueva configuración ha sido
        /// guardada correctamente, sino se mostrará el consiguiente mensaje de error.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOk_Click(object sender, EventArgs e)
        {
            ControlMessages msg = ControlMessages.getInstance();
            if (EsValido())
            {
                if (rbtXadesXl.Checked)
                {
                    Configuration.SignedType = "XADES-XL";
                }
                else
                {
                    Configuration.SignedType = "XADES-EPES";
                }

                Configuration.CompanyImage = txtCompanyImage.Text;
                Configuration.UrlSTServer = txtUrlTimeStamp.Text;
                Configuration.UrlIssued = txtIssuedDirectory.Text;
                Configuration.UrlRecived = txtReceivedDirectory.Text;
                Configuration.UrlDrafts = txtDraftsDirectory.Text;


                setDefaultInvoicesPath();

                try
                {

                    XmlFile.Save(Configuration, Globals.ThisAddIn.EnvironmentVariable + Paths.ConfigPath, Configuration.GetType());
                    XmlFile.Save(Configuration, System.Environment.GetEnvironmentVariable("APPDATA") + @"\config.xml", Configuration.GetType());
                }
                catch (Exception)
                {
                    MessageBox.Show(this, String.Concat(msg.getMessage(ControlMessages.Msg.ErrorSaveConfig), "\n", msg.getMessage(ControlMessages.Msg.InfoRestart)), msg.getMessage(ControlMessages.Msg.CaptionConfig), MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
                    return;
                }

                MessageBox.Show(this, msg.getMessage(ControlMessages.Msg.InfoSaveConfigOk), msg.getMessage(ControlMessages.Msg.CaptionConfig), MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
                this.Close();
            }
        }

        /// <summary>
        /// Método que maneja el evento que se produce al hacer click con el ratón sobre el botón de cancelar.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// Método que maneja el evento que se produce al hacer click con el ratón sobre el botón de examinar
        /// el directorio de las facturas emitidas.
        /// Abre un cuadro de diálogo para buscar el directorio donde se quieren almacenar las facturaes emitidas.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnIssuedBrowser_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog f = new FolderBrowserDialog();
            if (!(String.IsNullOrEmpty(txtIssuedDirectory.Text)) && Directory.Exists(txtIssuedDirectory.Text))
            {
                f.SelectedPath = txtIssuedDirectory.Text;
            }
            if (f.ShowDialog() == DialogResult.OK)
            {
                txtIssuedDirectory.Text = f.SelectedPath;
                //Configuration.UrlIssued = f.SelectedPath;
            }
        }

        /// <summary>
        /// Método que maneja el evento que se produce al hacer click con el ratón sobre el botón de examinar
        /// el directorio de las facturas recibidas.
        /// Abre un cuadro de diálogo para buscar el directorio donde se quieren almacenar las facturaes recibidas.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRecivedBrowser_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog f = new FolderBrowserDialog();
            if (!(String.IsNullOrEmpty(txtReceivedDirectory.Text)) && Directory.Exists(txtReceivedDirectory.Text))
            {
                f.SelectedPath = txtReceivedDirectory.Text;
            }
            if (f.ShowDialog() == DialogResult.OK)
            {
                txtReceivedDirectory.Text = f.SelectedPath;
                //Configuration.UrlRecived = f.SelectedPath;
            }
        }

        /// <summary>
        /// Método que maneja el evento que se produce al hacer click con el ratón sobre el botón de examinar
        /// el directorio de los borradores.
        /// Abre un cuadro de diálogo para buscar el directorio donde se quieren almacenar los borradores.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnDraftsBrowser_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog f = new FolderBrowserDialog();
            if (!(String.IsNullOrEmpty(txtDraftsDirectory.Text)) && Directory.Exists(txtDraftsDirectory.Text))
            {
                f.SelectedPath = txtDraftsDirectory.Text;
            }
            if (f.ShowDialog() == DialogResult.OK)
            {
                txtDraftsDirectory.Text = f.SelectedPath;
                //Configuration.UrlDrafts = f.SelectedPath;
            }
        }

        /// <summary>
        /// Método que maneja el evento que se produce al hacer click con el ratón sobre el botón de empresa.
        /// Se muestra el formulario con los datos de la empresa.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCompany_Click(object sender, EventArgs e)
        {
            FrmCompanyInformation frmCompany = new FrmCompanyInformation();
            frmCompany.Configuration = Configuration;
            frmCompany.Show();
        }

        private void lbCompanySettings_Click(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// Método que maneja el evento que se produce al cargar el formulario.
        /// Se inicializan los campos con los datos de la propiedad Configuración, los 
        /// cuales estaban almacenados en el archivo de configuración.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FrmSettings_Load(object sender, EventArgs e)
        {
            LoadLanguage();
            TstConfig = getTimeStampConfig();
            LoadComboBox(Globals.ThisAddIn.EnvironmentVariable + Paths.UrlTimeStamp, txtUrlTimeStamp);
            if (Configuration.SignedType.Equals("XADES-XL"))
            {
                rbtXadesXl.Checked = true;
            }
            else
            {
                rbtXadesEpes.Checked = true;
            }
            string invoiceDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + @"\Mis Facturas";

            if (!Directory.Exists(invoiceDirectory))
            {
                invoiceDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + @"\My Invoices";
            }

            setDefaultInvoicesPath();

            txtCompanyImage.Text = Configuration.CompanyImage;
            txtUrlTimeStamp.Text = Configuration.UrlSTServer;
            txtIssuedDirectory.Text = Configuration.UrlIssued;
            txtReceivedDirectory.Text = Configuration.UrlRecived;
            txtDraftsDirectory.Text = Configuration.UrlDrafts;
            txtTemplateType.Text = Configuration.UrlTemplate;
        }



        /// <summary>
        /// Método que maneja el evento que se produce al hacer click con el ratón sobre el botón de personalizar.
        /// Se muestra el formulario con los datos de la empresa.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnTemplateTypeBrowser_Click(object sender, EventArgs e)
        {
            OpenFileDialog f = new OpenFileDialog();
            f.Filter = "Plantillas (*.xltx)|*.xltx|Documentos de Excel (*.xlsx)|*.xlsx";
            f.RestoreDirectory = true;
            if (!(String.IsNullOrEmpty(Configuration.UrlTemplate)) && File.Exists(Configuration.UrlTemplate))
            {
                f.InitialDirectory = txtTemplateType.Text;
            }
            if (f.ShowDialog() == DialogResult.OK)
            {
                txtTemplateType.Text = f.FileName;
                Configuration.UrlTemplate = txtTemplateType.Text;
            }
        }



        /// <summary>
        /// Asigna el directorio de facturas por defecto, en caso de que no se hayan configurado aun o los dejen vacios
        /// </summary>
        private void setDefaultInvoicesPath()
        {
            try
            {

                string invoiceDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + @"\Mis Facturas";

                if (Directory.Exists(invoiceDirectory))
                {
                    if (string.IsNullOrEmpty(Configuration.UrlIssued))
                        Configuration.UrlIssued = invoiceDirectory + @"\Emitidas";
                    if (string.IsNullOrEmpty(Configuration.UrlRecived))
                        Configuration.UrlRecived = invoiceDirectory + @"\Recibidas";
                    if (string.IsNullOrEmpty(Configuration.UrlDrafts))
                        Configuration.UrlDrafts = invoiceDirectory + @"\Borradores";
                }
                else
                {

                    invoiceDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + @"\My Invoices";

                    if (string.IsNullOrEmpty(Configuration.UrlIssued))
                        Configuration.UrlIssued = invoiceDirectory + @"\Issued";
                    if (string.IsNullOrEmpty(Configuration.UrlRecived))
                        Configuration.UrlRecived = invoiceDirectory + @"\Received";
                    if (string.IsNullOrEmpty(Configuration.UrlDrafts))
                        Configuration.UrlDrafts = invoiceDirectory + @"\Drafts";

                }
            }
            catch (Exception) { }
        }


        private void btnCompanyImage_Click(object sender, EventArgs e)
        {
            OpenFileDialog f = new OpenFileDialog();
            f.Filter = "Archivos de imagen (*.jpg)|*.jpg|Archivos de imagen (*.JPEG)|*.JPEG|Archivos de imagen (*.png)|*.png|Archivos de imagen (*.bmp)|*.bmp|Todos los archivos (*.*)|*.*";
            f.RestoreDirectory = true;
            //if (!(String.IsNullOrEmpty(Configuration.UrlLog)) && File.Exists(Configuration.UrlLog))
            //{
            //    f.InitialDirectory = txtTemplateType.Text;
            //}
            if (f.ShowDialog() == DialogResult.OK)
            {
                txtCompanyImage.Text = f.FileName;
                Configuration.CompanyImage = txtCompanyImage.Text;
            }
        }

        #endregion

        #region "Public Methods"

        /// <summary>
        /// Método que comprueba si los datos introducidos por el usuario son correctos.
        /// En caso negativo se muestra un mensaje informativo indicando aquellos datos que no son válidos.
        /// </summary>
        /// <returns>Devuelve true o false dependiendo de si los datos son correctos o no</returns>
        public bool EsValido()
        {
            ControlMessages cmsg = ControlMessages.getInstance();
            string msg = String.Concat(cmsg.getMessage(ControlMessages.Msg.InfoCorrectFields), "\n\n");
            bool correcto = true;
            if (string.IsNullOrEmpty(txtUrlTimeStamp.Text))
            {
                msg = string.Concat(msg, cmsg.getMessage(ControlMessages.Msg.InfoUrlSTM), "\n");
                correcto = false;
            }
            if (string.IsNullOrEmpty(txtIssuedDirectory.Text))
            {
                msg = string.Concat(msg, cmsg.getMessage(ControlMessages.Msg.InfoUrlIssuedDirectory), "\n");
                correcto = false;
            }
            if (string.IsNullOrEmpty(txtReceivedDirectory.Text))
            {
                msg = string.Concat(msg, cmsg.getMessage(ControlMessages.Msg.InfoUrlRecivedDirectory), "\n");
                correcto = false;
            }
            if (string.IsNullOrEmpty(txtDraftsDirectory.Text))
            {
                msg = string.Concat(msg, cmsg.getMessage(ControlMessages.Msg.InfoUrlDraftsDirectory), "\n");
                correcto = false;
            }
            if (correcto)
            {
                return true;
            }
            MessageBox.Show(this, msg, cmsg.getMessage(ControlMessages.Msg.CaptionConfig), MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
            return false;
        }

        /// <summary>
        /// Método que carga el archivo de idioma y establece los textos de los controles
        /// en el idioma que corresponde.
        /// </summary>
        public void LoadLanguage()
        {
            try
            {
                Language labels = Language.getInstance();
                this.Text = labels.getLabels(this.Name);
                gbxAppearance.Text = labels.getLabels(gbxAppearance.Name);
                gbxManagement.Text = labels.getLabels(gbxManagement.Name);
                gbxSecurity.Text = labels.getLabels(gbxSecurity.Name);
                gbxSignedType.Text = labels.getLabels(gbxSignedType.Name);
                gbxUrlTimeStamp.Text = labels.getLabels(gbxUrlTimeStamp.Name);

                btnCancel.Text = labels.getLabels(btnCancel.Name);
                btnCompany.Text = labels.getLabels(btnCompany.Name);

                btnDraftsBrowser.Text = labels.getLabels(btnDraftsBrowser.Name);
                btnIssuedBrowser.Text = labels.getLabels(btnIssuedBrowser.Name);
                btnOk.Text = labels.getLabels(btnOk.Name);
                btnRecivedBrowser.Text = labels.getLabels(btnRecivedBrowser.Name);
                btnTemplateTypeBrowser.Text = labels.getLabels(btnTemplateTypeBrowser.Name);

                lbCompanySettings.Text = labels.getLabels(lbCompanySettings.Name);
                lbDraftsDirectory.Text = labels.getLabels(lbDraftsDirectory.Name);
                lbIssuedDirectory.Text = labels.getLabels(lbIssuedDirectory.Name);
                lbRecivedDirectory.Text = labels.getLabels(lbRecivedDirectory.Name);
                lbTemplateType.Text = labels.getLabels(lbTemplateType.Name);

                lbCompanyImage.Text = labels.getLabels(lbCompanyImage.Name);
                btnCompanyImage.Text = labels.getLabels(btnCompanyImage.Name);

                btnNewTimeStamp.Text = labels.getLabels(btnNewTimeStamp.Name);
                btnConfigTimeStamp.Text = labels.getLabels(btnConfigTimeStamp.Name);

            }
            catch (Exception)
            {
                ControlMessages msg = ControlMessages.getInstance();
                MessageBox.Show(msg.getMessage(ControlMessages.Msg.ErrorLoadLanguage), msg.getMessage(ControlMessages.Msg.CaptionConfig), MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        }


        /// <summary>
        /// Método que se encarga de cargar un combobox a partir de un string con los datos.
        /// </summary>
        /// <param name="path">String que contiene el paht donde se encuentra el archivo con los valores que se van a cargar en el combo</param>
        /// <param name="cbx">Combobox que se desea cargar</param>
        public void LoadComboBox(string path, ComboBox cbx)
        {
            try
            {
                for (int i = 0; i < TstConfig.TimeStamp.Count; i++)
                {
                    cbx.Items.Add(TstConfig.TimeStamp[i].Url);
                }
                //string names = ReadFile(path);
                //string[] data = names.Split('\t');
                //for (int i = 0; i < data.Length; i++)
                //{
                //    cbx.Items.Add(data[i]);
                //}
            }
            catch (Exception)
            {
                ControlMessages msg = ControlMessages.getInstance();
                MessageBox.Show(msg.getMessage(ControlMessages.Msg.ErrorLoadUrlTimeStamp), msg.getMessage(ControlMessages.Msg.CaptionCompanyInformation), MessageBoxButtons.OK, MessageBoxIcon.Error);
            }

        }

        /// <summary>
        /// Método que devuelve una cádena con los datos almacenados en el archivo especificado en 
        /// el path que recibe por parámetro.
        /// </summary>
        /// <param name="path">Ruta del archivo que vamos a leer</param>
        /// <returns>Un string con los datos en forma de cadena</returns>
        public string ReadFile(string path)
        {
            using (StreamReader sr = new StreamReader(path, Encoding.Default))
            {
                return sr.ReadToEnd();
            }
        }

        #endregion

        private void btnNewTimeStamp_Click(object sender, EventArgs e)
        {
            FrmTimeStampConfig f = new FrmTimeStampConfig();
            f.TstConfig = TstConfig;
            if (f.TstConfig != null)
            {
                f.ShowDialog();
                if (f.Save)
                {
                    try
                    {

                        XmlFile.Save(f.TstConfig, System.Environment.GetEnvironmentVariable("APPDATA") + Paths.UrlTimeStamp, f.TstConfig.GetType());
                        TstConfig = f.TstConfig;
                        txtUrlTimeStamp.Items.Clear();
                        LoadComboBox(Globals.ThisAddIn.EnvironmentVariable + Paths.UrlTimeStamp, txtUrlTimeStamp);
                        txtUrlTimeStamp.Refresh();
                        txtUrlTimeStamp.Text = f.defaultTst.Url;
                    }
                    catch (Exception)
                    {
                        return;
                    }
                }
            }
        }

        private void btnConfigTimeStamp_Click(object sender, EventArgs e)
        {
            FrmTimeStampConfig f = new FrmTimeStampConfig();
            f.TstConfig = TstConfig;
            if (f.TstConfig != null)
            {
                f.defaultTst = getTimeStamp();
                f.ShowDialog();
                if (f.Save)
                {
                    try
                    {

                        XmlFile.Save(f.TstConfig, System.Environment.GetEnvironmentVariable("APPDATA") + Paths.UrlTimeStamp, f.TstConfig.GetType());
                        TstConfig = f.TstConfig;
                        txtUrlTimeStamp.Items.Clear();
                        LoadComboBox(Globals.ThisAddIn.EnvironmentVariable + Paths.UrlTimeStamp, txtUrlTimeStamp);
                        txtUrlTimeStamp.Refresh();
                        txtUrlTimeStamp.Text = f.defaultTst.Url;
                    }
                    catch (Exception)
                    {
                        return;
                    }
                }
            }
        }

        public TimeStampConfig getTimeStampConfig()
        {
            XmlSerializer serializer = null;
            System.IO.StreamReader r = null;
            try
            {
                serializer = new XmlSerializer(typeof(TimeStampConfig));
                r = new System.IO.StreamReader(System.Environment.GetEnvironmentVariable("APPDATA") + Paths.UrlTimeStamp);
                TimeStampConfig tst = ((TimeStampConfig)serializer.Deserialize(r));
                r.Close();
                return tst;
            }
            catch (FileNotFoundException)
            {
            }
            catch (DirectoryNotFoundException)
            {
            }
            catch (InvalidOperationException)
            {
                r.Close();
            }

            return null;
        }

        public TimeStamp getTimeStamp()
        {
            for (int i = 0; i < TstConfig.TimeStamp.Count; i++)
            {
                if (TstConfig.TimeStamp[i].Url.Equals(txtUrlTimeStamp.Text))
                {
                    return TstConfig.TimeStamp[i];
                }
            }
            return null;
        }

        private void txtUrlTimeStamp_SelectedIndexChanged(object sender, EventArgs e)
        {
            Configuration.UrlSTServer = txtUrlTimeStamp.Text;
            TimeStamp t = getTimeStamp();
            Configuration.UserNameSTServer = t.UserName;
            Configuration.PassworSTServer = t.Password;
        }

        
    }
}
